package com.jackrain.util;

import com.alibaba.dubbo.common.utils.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.util.TypeUtils;
import com.aliyun.openservices.ons.api.Message;
import com.aliyun.openservices.ons.api.bean.ProducerBean;
import com.aliyun.openservices.ons.api.impl.util.MsgConvertUtil;
import com.jackrain.nea.config.Resources;
import com.jackrain.nea.exception.NDSException;
import com.jackrain.nea.exception.NDSObjectNotFoundException;
import com.jackrain.nea.ext.common.MessageInfo;
import com.jackrain.nea.ext.common.MessageType;
import com.jackrain.nea.util.*;
import com.jackrain.nea.web.face.User;
import com.jackrain.nea.web.query.QueryEngine;
import com.jackrain.nea.web.security.SecurityWebUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.FastDateFormat;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Date;
import java.util.HashMap;
import java.util.UUID;

/**
 * Created by nathan on 2016/7/26.
 */
@Slf4j
public class WebUtils {


    /**
     * 获取客户端IP
     * @param request
     * @return
     */
    public static String getIpAddress(HttpServletRequest request){
        String ip = request.getHeader("x-forwarded-for");
        if (ip != null && ip.contains(",")) {
            ip = ip.split(",")[0];
        }
        if (!checkIp(ip)){
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (!checkIp(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (!checkIp(ip)) {
            ip = request.getHeader("X-Real-IP");
        }
        if (!checkIp(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    private static boolean checkIp(String ip){
        if(ip == null || ip.length() == 0 || "unkown".equalsIgnoreCase(ip)){
            return false;
        }
        return true;
    }

    /**
     * DES对密码进行加密
     * @param data
     * @param desKey
     * @return
     */
    public static String encryptBasedDes(String data,byte[] desKey) {
          String encryptedData = null;
           try {
                     // DES算法要求有一个可信任的随机数源
                        SecureRandom sr = new SecureRandom();
                       DESKeySpec deskey = new DESKeySpec(desKey);
                      // 创建一个密匙工厂，然后用它把DESKeySpec转换成一个SecretKey对象
                      SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
                       SecretKey key = keyFactory.generateSecret(deskey);
                      // 加密对象
                      Cipher cipher = Cipher.getInstance("DES");
                      cipher.init(Cipher.ENCRYPT_MODE, key, sr);
                     // 加密，并把字节数组编码成字符串
                     encryptedData = new sun.misc.BASE64Encoder().encode(cipher.doFinal(data.getBytes()));
                   } catch (Exception e) {
           //            log.error("加密错误，错误信息：", e);
                      throw new RuntimeException(Resources.getMessage("password-des-fail"), e);
                   }
              return encryptedData;
    }


    /**
     * DES对密码进行解密
     * @param data
     * @param desKey
     * @return
     */
    public static String decryptBasedDes(String data,byte[] desKey) {

        String decryptedData = null;
        try {
            byte[] decodeBuffer = new sun.misc.BASE64Decoder().decodeBuffer(data);

            // DES算法要求有一个可信任的随机数源
            SecureRandom sr = new SecureRandom();
            DESKeySpec deskey = new DESKeySpec(desKey);
            // 创建一个密匙工厂，然后用它把DESKeySpec转换成一个SecretKey对象
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            SecretKey key = keyFactory.generateSecret(deskey);
            // 加密对象
            Cipher cipher = Cipher.getInstance("DES");
            cipher.init(Cipher.DECRYPT_MODE, key, sr);
            // 加密，并把字节数组编码成字符串
            decryptedData = new String(cipher.doFinal(decodeBuffer));
          } catch (Exception e) {
            //            log.error("加密错误，错误信息：", e);
            throw new RuntimeException(Resources.getMessage("password-des-fail"), e);
        }
        return decryptedData;
    }

    /**
     * 认证验证码是否通过
     * @param captcha
     * @return
     */

    public Boolean verCaptcha(String captcha){
        String s = WebUtils.decryptBasedDes(captcha, ("raincloud").getBytes());
        Long before = Long.parseLong(s);
        Long current = (new Date()).getTime();
        Long diff = before==null ? null : (current - before)/1000;
        if(diff == null || diff > 30){
            return false;
        }
        return true;
    }

    /**
     * Find id of specified object by it's alternate key's value, throw exception if object not found or errors occur.
     *
     * @param tableName name of table object.
     *     PLEASE INFORM THE PROJECT MANAGER IF YOU FOUND THE OBJECT NAME IS NOT IDENTICAL TO DATABASE TABLE NAME.
     * @param keyName alternate key's name, normally it's a String type and act as displayer that object
     * @param keyValue the value of keyName, used for identify the object.
     * @return object id
     */
    public static long findObjectIdByAlternateKey(String tableName, String keyName, String keyValue,String buffer) throws NDSObjectNotFoundException {
        Exception ex=null;
        StringBuffer sqlBuffer = new StringBuffer();
        String sql="select id from "+ tableName+" where "+keyName+" = '"+ keyValue+"'";
        sqlBuffer.append(sql);
        if (StringUtils.isNotEmpty(buffer)){
            sqlBuffer.append(buffer);
        }

        Object o= QueryEngine.getInstance().doQueryOne(sqlBuffer.toString());
        if(o != null){
            return TypeUtils.castToLong(o);
        }else {
            throw new NDSObjectNotFoundException("@object-not-found@:" + tableName + "(" + keyName + "=" + keyValue + ")");
        }
    }

    /**
     * @param tempCode 短信模板
     * @param phone 发送手机号
     * @param user  操作用户
     * @param isVerCode  是否验证码
     * @param isSetting  是否短信设置
     * @return
     */
    public static ValueHolder sendMessage(String tempCode, String phone, String params, int utype, User user, Boolean isVerCode, Boolean isSetting){
        ValueHolder vh = new ValueHolder();
        if (phone == null){
            vh.put("code",-1);
            vh.put("message","phone must be not nullable");
            return vh;
        }
        if (user == null){
            user = SecurityWebUtils.getUser(893);
        }
        JSONObject template;
        if(isSetting){
            template= QueryEngine.getInstance().
                    doQueryObject("select sign,tempcode,subject,sms_content_e from sms_storetemp " +
                            "where tempcode=? and c_store_id=?",new Object[]{tempCode,user.getStoreId()});
        }else{
            template= QueryEngine.getInstance().
                    doQueryObject("select sign,tempcode,subject,sms_content_e from sms_template " +
                            "where tempcode=?",new Object[]{tempCode});
        }
        if(template == null){
            vh.put("code",-1);
            vh.put("message","message template must be not nullable");
            return vh;
        }

        //调用短信服务
        Object o = ReferenceUtil.refer(ApplicationContextHandle.getApplicationContext(), "com.jackrain.nea.sys.Command", "SendMessage", "1.0");
        //随机5位数
        String code =  Tools.getRandomNum(5);
        HashMap map = new HashMap();
        MessageInfo messageInfo = new MessageInfo();
        messageInfo.setType(MessageType.SMS2);


        //参数params封装 ad_client_id 不能为空
        JSONObject senderContext = new JSONObject();
        senderContext.put("sign",template.getString("sign"));
        senderContext.put("tempcode",template.getString("tempcode"));
        senderContext.put("sms_content_e",template.getString("sms_content_e"));
        senderContext.put("subject",template.getString("subject"));
        senderContext.put("user", user);
        senderContext.put("ad_client_id", user.getClientId());
        senderContext.put("utype", utype);
        if(isVerCode){
            senderContext.put("params","{'code':'"+code+"'}");
        }else{
            senderContext.put("params",params);
        }

        senderContext.put("phone",phone);
        map.put("message", messageInfo);
        map.put("params", senderContext);

        //调用短信服务
        try {
            vh = (ValueHolder)o.getClass().getDeclaredMethod("execute", new Class[]{HashMap.class}).invoke(o, map);
        } catch (Exception e) {
            throw new NDSException("send message failed",e);
        }

        int resultCode = TypeUtils.castToInt(vh.get("code"));

        if(isVerCode){
            if (resultCode >= 0) {
                Date date = new Date();
                Long id = QueryEngine.getInstance().getSequence("rc_msgauth");
                String message = "";
                int result = QueryEngine.getInstance().executeUpdate("insert into rc_msgauth" +
                                "(id,phone,code,creationdate,message) values (?,?,?,?,?)",
                        new Object[]{id,phone,code, date, message});
                JSONObject jsonObject = QueryEngine.getInstance().doQueryObject("select id from rc_msgauth where phone = ? and code = ?", new Object[]{phone,code});
                int msgId = jsonObject.getInteger("id");
                vh.put("code", 0);
                vh.put("result", msgId);
            }
        }
        return vh;
    }

    public static String convertToHexString(byte data[]) {
        StringBuffer strBuffer = new StringBuffer();
        for (int i = 0; i < data.length; i++) {
            strBuffer.append(Integer.toHexString(0xff & data[i]));
        }
        return strBuffer.toString();
    }


    public static void CallInterface(Long adClientId,String topic,String tag,Object param) throws Exception{
        ProducerBean producerBean = (ProducerBean) ApplicationContextHandle.getBean(ProducerBean.class);
        JSONObject result = new JSONObject();
        result.put("clientId",adClientId);
        result.put("topic",topic);
        result.put("tag",tag);
        result.put("data",param);
        Message msg = new Message("OMS_CALL_INTERFACE",tag, MsgConvertUtil
                .objectSerialize(JSON.toJSONString(result,new SerializerFeature[]{SerializerFeature.WriteMapNullValue})));
        msg.setKey(UUID.randomUUID().toString());
        producerBean.send(msg);

    }


}
